home *** CD-ROM | disk | FTP | other *** search
- ; map8_accurate.s
- ; MACHINE: RISC OS
- ; LANGUAGE: OBJASM assembler
- ; AUTHOR: Cy Booker, cy@cheepnis.demon.co.uk
- ; LICENSE: FreeWare, Copyright (c) Cy Booker 1996
- ; PURPOSE: Given an arbitary 48-bit colour, what is the closest 8-bit colour number?
- ;
- ; the weights we want are:
- ; Red * 0.212671 * 14 ~= 3
- ; Green * 0.715160 * 14 ~= 10
- ; Blue * 0.072169 * 14 ~= 1
- ;
- ; error in using the approximation {3/14, 10/14, 1/14} is < 0.000001 !
- ;
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- bits * 16 ; number of bits per primary
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ; in middle we have |intensity-difference| <-- 2^|bits| - 1
- ; (pathalogical case). Ordinarily can assume |diff| <= 2^|bits - 1|
- ;
- ; maximum distance is (2^|bits|-1)^2 * 3 * 14
- ; we want this to be less than 2^32 so can work with 32-bit unsigned integers
- ;
- ; so for arbitary |bits| of colour intensity we end out with
- ; (2^|bits|-1)^2 * 3 * 14 / (2^n) < 2^32
- ; n.log2 > -32.log2 + log((2^|bits|-1)^2 * 3 * 14)
- ; n.log2 > -32.log2 + 2.|bits|.log2 + log(3 * 14)
- ; n > 2.|bits| - 32 + log(3*14)/log2
- ; n > 2.|bits| - 26.6
- ; so set shift (right) to 2*bits - 26
-
-
- shift * (2 * bits) - 26
- [ shift < 0
- shift * 0 ; but no need for negative shifts!
- ]
-
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
- GET OS:Hdr.os
-
-
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- MACRO
- $label Op1Shift $op1, $dest, $src, $shift
- [ ($shift) = 0
- $op1 $dest, $src
- |
- [ ($shift) < 0
- $op1 $dest, $src, LSL #-($shift)
- |
- $op1 $dest, $src, LSR #($shift)
- ]
- ]
- MEND
-
- MACRO
- $label Op2Shift $op2, $dest, $srca, $srcb, $shift
- [ ($shift) = 0
- $op2 $dest, $srca, $srcb
- |
- [ ($shift) < 0
- $op2 $dest, $srca, $srcb, LSL #-($shift)
- |
- $op2 $dest, $srca, $srcb, LSR #($shift)
- ]
- ]
- MEND
-
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;
-
- EXPORT map_scaled_rgb_to_palette_index
-
- AREA |ARM$$code|, CODE, READONLY
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;
- ; In R0 -> structure
- ; structure[3] = pointer to array of {red, green, blue}
- ; structure[4] = number of entries in array (>= 1)
- ; R1 = red nominally [0, 0xffff], but clipped as necessary
- ; R2 = green nominally [0, 0xffff], but clipped as necessary
- ; R3 = blue nominally [0, 0xffff], but clipped as necessary
- ; Out R0 <-- index into array
- ; structure[0] = error in approximating red intensity
- ; structure[1] = error in approximating green intensity
- ; structure[2] = error in approximating blue intensity
- ;
-
- ROUT
-
- map_scaled_rgb_to_palette_index
-
- str RN a1
- red RN a2
- grn RN a3
- blu RN a4
- r RN v1 ; r < g
- g RN v2 ; g < b
- b RN v3
- dmin RN v4
- dist RN v5
- palette RN v6
- best RN ip ; implicit != str
- i RN str
- t RN lr
-
- STMFD sp!, {a1, v1-v6, lr}
- MOV t, #1 << bits
- CMP red, t ; ensure in range [0, 0xffff]
- MOVHS red, #0
- SUBGE red, t, #1
- CMP grn, t
- MOVHS grn, #0
- SUBGE grn, t, #1
- CMP blu, t
- MOVHS blu, #0
- SUBGE blu, t, #1
- ;
- MOV dmin, #&ffffffff
- LDR palette, [str, #4*3]
- LDR i, [str, #4*4]
- ; for (i= ncolours; (i > 0); i--)
- 0
- LDMIA palette!, {r, g, b}
- SUBS r, r, red
- RSBLT r, r, #0 ; speeds up MUL instruction
- MUL t, r, r
- [ shift > 0
- Op1Shift MOVS, dist, t, shift ; dist = red * 1
- Op2Shift ADC, dist, dist, t, shift - 1 ; dist = red * 3
- |
- ADD dist, t, t, LSL #1 ; dist = red * 3
- ]
-
- SUBS g, g, grn
-